<?php
namespace Quality\Start\App\Service;

class HashGenerator
{
    /**
     * Default salt prefix
     *
     * @see http://www.php.net/security/crypt_blowfish.php
     * @var string
     */
    protected static $saltPrefix = '2a';

    /**
     * Default hashing cost (4-31)
     * @var integer
     */
    protected static $defaultCost = 13;

    /**
     * Salt length
     * @var integer
     */
    protected static $saltLength = 22;

    /**
     * Hash a string
     *
     * @param  string  $string The string
     * @param  integer $cost   The salt with 22 characters
     * @return string
     */
    public static function hash($string, $salt = null) {
        if (!$salt || strlen($salt) != self::$saltLength) {
            $salt = self::generateRandomSalt();
        }

        $hashString = self::generateHashString($salt);

        return crypt($string, $hashString);
    }

    /**
     * Check a hashed string
     *
     * @param  string $string The string
     * @param  string $hash   The hash
     * @return boolean
     */
    public static function check($string, $hash) {
        return (crypt($string, $hash) === $hash);
    }

    /**
     * Generate a random base64 encoded salt
     *
     * @return string
     */
    private static function generateRandomSalt() {
        $salt = uniqid(mt_rand(), true);

        for ($i = 0; $i < 1000; ++$i) $salt = md5($salt);

        return substr($salt, 0, self::$_saltLength);
    }

    /**
     * Build a hash string for crypt()
     *
     * @param  string $salt  The salt
     * @return string
     */
    private static function generateHashString($salt) {
        return sprintf('$%s$%02d$%s$', self::$saltPrefix, self::$_defaultCost, $salt);
    }
}
